home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / NEWSOFT / OCTOBER / CSDVAR / BasAsmLib (.txt) < prev    next >
RISC OS BBC BASIC V Source  |  1996-10-26  |  12KB  |  352 lines

  1.  >BasAsmLib 1.00 
  2.  Musus Umbra, 1996
  3.  *******************************************************************
  4.  ** Some (if not all) of these routines require that your code is **
  5.  ** assembled using 'pass%' as the OPT parameter, and 'code%' as  **
  6.  ** the base address (initial O%/P%).                             **
  7.  *******************************************************************
  8.  ==================================================================
  9.  Assemble a routine to display all the register contents (except
  10.  R14) without altering any of them!  Very handy debugging function,
  11.  this one.
  12.  NB: You only need to assemble this once and should BL to it when
  13.  you need it (or use one of the debugging macros below)
  14.  ==================================================================
  15. showregs
  16. [OPT pass%
  17. B       __showregs
  18. .__super_stack    equd    0
  19. .__debug_link     equd    0
  20. ;.__debug_stack    equs    
  21. 96,"!")   :.__enddebug_stack
  22. ,.__debug_buffer   equs    "000000000000"
  23. .__showregs
  24. str     r13,__super_stack
  25. str     r14,__debug_link
  26.  adr     r13,__enddebug_stack
  27. mov     r14,r0
  28. ldr     r0,__debug_link
  29. stmdb   r13!,{r0}
  30. ldr     r0,__super_stack
  31. stmdb   r13!,{r0}
  32. mov     r0,r14
  33. stmdb   r13!,{r0-r12}
  34. mov     r6,#0   
  35. str     r13,__debug_stack
  36. ldr     r13,__super_stack
  37. .__regloop
  38. swi     256+
  39. cmp     r6,#10
  40. addlt   r0,r6,#48
  41. swilt   "XOS_WriteC"
  42. movlt   r0,#32
  43. swige   256+
  44. addge   r0,r6,#38
  45. swi     "XOS_WriteC"
  46. swi     256+
  47. str     r13,__super_stack
  48. ldr     r13,__debug_stack
  49. ldmia   r13!,{r0}
  50. str     r13,__debug_stack
  51. ldr     r13,__super_stack
  52. adr     r1,__debug_buffer
  53. mov     r2,#32
  54. swi     "XOS_ConvertHex8"
  55. swi     "XOS_Write0"
  56. swi     "XOS_WriteS"
  57. equd    &00202020       
  58. add     r6,r6,#1
  59. cmp     r6,#14
  60. moveq   r6,#15
  61. ands    r0,r6,#3
  62. swieq   "XOS_NewLine"
  63. cmp     r6,#15
  64. ble     __regloop
  65. str     r13,__super_stack
  66. C"adr     r13,__enddebug_stack-8
  67. ldmdb   r13!,{r0-r12}
  68. ldr     r13,__super_stack
  69. ldr     r14,__debug_link
  70. movs    pc,r14
  71.  ==================================================================
  72.  A nice debugging thang (requires that you include FNshowregs
  73.  somewhere, see later)
  74.  Displays the text 'a$' and a register dump.
  75.  Sets SHOWREGS_USED to some non-zero value; it's suggested that you
  76.  have 'SHOWREGS_USED=0' at the start of your program (outside the
  77.  FOR pass% loop) and at some convenient point use something like:
  78.       ... your code ...
  79.       ]:IF SHOWREGS_USED:[OPT pass%:FNshowregs:]
  80.       [OPT pass%
  81.       ... your code ...
  82.  ==================================================================
  83. debug(a$)
  84. [OPT pass%
  85. .SHOWREGS_USED
  86. stmfd r13!,{r14}
  87. \'SWI "XOS_NewLine":SWI "XOS_NewLine"
  88. ])SWI "XOS_WriteS":EQUS a$:EQUB 0:ALIGN
  89. SWI "XOS_NewLine"
  90. bl  __showregs
  91. ldmfd r13!,{r14}
  92.  ==================================================================
  93.  Display the (null terminated) string pointed to by register 'r%'
  94.  (if register 'r%' isn't 0)
  95.  ==================================================================
  96. debps(r%)
  97. [OPT pass%
  98. stmfd    r13!,{r0,r14}
  99. mov      r0,r%
  100. cmp      r0,#0
  101. swine    "XOS_Write0"
  102. swi      "XOS_NewLine"
  103. ldmfd    r13!,{r0,r14}
  104.  ==================================================================
  105.  Print the message 'a$' followed by the (null terminated) string
  106.  pointed to by register 'r%' (if register 'r%' isn't 0)
  107.  ==================================================================
  108. debpp(a$,r%)
  109. [OPT pass%
  110. stmfd    r13!,{r0,r14}
  111. swi      "XOS_WriteS"
  112. equs     a$:equb 0:align
  113. mov      r0,r%
  114. cmp      r0,#0
  115. swine    "XOS_Write0"
  116. swi      "XOS_NewLine"
  117. ldmfd    r13!,{r0,r14}
  118.  ==================================================================
  119.  Assemble two instructions that place the address 'dest%' in
  120.  register 'reg%' (ie. a long ADR directive).  'dest%' must be
  121.  within 64K of P% (some limit, huh?)
  122.  FNadr is the equivalent of ADR
  123.  Use FNadrc when you want the ADR to be conditionally executed
  124.  ==================================================================
  125. adr(reg%,dest%)=
  126. adrc("AL",reg%,dest%)
  127. adrc(condition$,reg%,dest%)
  128. (dest%-P%)>65536 
  129.  1,"ADR destination out of range at &"+
  130. (~P%)
  131. A c$=
  132. __toupper(
  133. condition$,1,1))+
  134. __toupper(
  135. condition$,2,1))
  136. 0 cc%=
  137. "EQNECSCCMIPLVSVCHILSGELTGTLEALNV",c$)
  138.  cc%=0 
  139.  1, "Bad condition code in ADR at &"+
  140. (~P%)
  141. 6 cc%=(cc%-1) 
  142.  2:diff%=dest%-(P%+8):op1%=(cc%<<28)
  143. : op1%+=&024F0000:op1%+=(reg%<<12):op1%+=
  144. (diff%) 
  145. E op2%=(cc%<<28):op2%+=&02400C00:op2%+=(reg%<<16):op2%+=(reg%<<12)
  146. A op2%+=
  147. (diff%)>>8 
  148.  &FF:
  149.  diff%>=0 
  150.  op1%+=4<<20:op2%+=4<<20
  151. % [OPT pass%:EQUD op1%:EQUD op2%:]
  152.  ==================================================================
  153.  Extract the SWI number of a swi name in the module being compiled.
  154.  Requires that the module header is at 'code%'.
  155.  eg. to use the SWI "SomeModule_Example", you would use the macro:
  156.    swi FNmy_swi("Example")
  157.  This is handy as it means that when assembling a module that uses
  158.  its own SWIs, you don't have to fiddle or use absolute numbers,
  159.  or have a copy of the module loaded.
  160.  ==================================================================
  161. my_swi(leaf$)
  162.  switable%,swichunk%,swinumber%,i%,a$
  163.  (pass% 
  164.  3) <= 1 
  165.  = &20000
  166. H switable%=code%+code%!&24:swichunk%=(code%!&1C)+&20000:swinumber%=0
  167.  switable%=0 
  168.  swichunk%=0 
  169.  1,"No swi table/chunk"
  170. 3 i%=0:
  171.  ?switable%:switable%+=1:
  172. :switable%+=1
  173.  ?switable% 
  174.  a$=""
  175. C      
  176.  ?switable%:a$+=
  177. ?switable%:switable%+=1:
  178. :switable%+=1
  179. .      
  180.  a$=leaf$ 
  181.  swinumber%=i%+swichunk%
  182.       i%+=1
  183. &    
  184.  swinumber%<>0 
  185.  ?switable%=0
  186. -    
  187.  1,"Module doesn't provide any SWIs"
  188.  swinumber%=0 
  189.  1,"Can't find local swi '"+leaf$+"'"
  190. =swinumber%
  191.  ==================================================================
  192.  Another module one this:
  193.  returns a string that is padded with tab characters so that when
  194.  prettyprinted it is (at least) 16 characters wide.
  195.  Good for module 'help strings', eg.
  196.  .help_string equs FNtabpad(title$)+version$):equb 0
  197.  ==================================================================
  198. tabpad(a$)
  199. (a$)<8 
  200.  a$+=
  201. (a$)<16 
  202.  a$+=
  203.  ==================================================================
  204.  Easy way of including 'w' 'hard' spaces (CHR$31) into an equs
  205.  (eg. in a help string for a module)
  206.  .command_help equs FNw(10)+"This is indented 10 spaces!"
  207.  ==================================================================
  208. h(w):=
  209.  ==================================================================
  210.  Convert a string into a (shorter) equivalent to be PrettyPrinted
  211.  using the RISC OS dictionary.  Useful for module help text, syntax
  212.  messages, etc
  213.  ==================================================================
  214. init_os_dict_tokenise
  215.  __tok_buffer% 512
  216. ,   __tokenise% = 
  217. assemble_longest_match
  218. (   __dictionary% = 
  219. build_dictionary
  220. os_dict_tokenise(a$)
  221.  A%,R%,E%,T%,O%
  222.    $__tok_buffer% = a$
  223. 6   A%=__tok_buffer%:
  224.  start at beginning of string
  225.    B%=__dictionary%
  226.    O%=A%:E%=A%+
  227. 1   ?E%=0 : 
  228.  terminate with the good ol' null
  229.       R%=
  230. (__tokenise%)
  231. E      
  232.  !R% 
  233.  ?O%=27:O%?1=!R%:O%+=2:A%=R%!4 
  234.  ?O%=?A%:A%+=1:O%+=1
  235.  A%>=E%
  236.    ?O%=13
  237. =$__tok_buffer%
  238.  INTERNAL USE ROUTINES
  239. __toupper(a$)
  240.  a$>="a" 
  241.  a$<="z" 
  242. (a$)-32)
  243. build_dictionary
  244.  buffer%,tokenv$,token%,token$,B%
  245.  &02," the ",&03,"director",&04,"filing system",&05,"current"
  246.  &06," to a variable. Other types of value can be assigned with *"
  247.  &07,"file",&08,"default ",&09,"tion",&0A,"*Configure ",&0B,"name"
  248.  &0C," server",&0D,"number"
  249.  &0F," one or more files that match the given wildcard",&10," and "
  250.  &11,"relocatable module",&13,"sets the "
  251.  &18," is used to print a hard copy of the screen on EPSON-"
  252.  &1A,"printe",&1C," select",&1D,"xpression",&1F,"sprite"
  253.  &20," displays",&21,"free space",&22," {off}",&23,"library"
  254.  &24,"parameter",&25,"object",&26," all ",&27,"disc",&28," to "
  255.  &29," is "
  256.  &00,""
  257.  buffer% 1024 : 
  258.  allocate 1K for the dictionary thang
  259.    B%=0
  260. ,      
  261.  tokenv$,token$:token%=
  262. (tokenv$)
  263. !      B%?buffer%=token%:B%+=1
  264. I      
  265.  (B%+
  266. (token$)+1)>=1024 
  267.  1,"Buffer to small for dictionary"
  268.       $(B%+buffer%)=token$
  269.       B%+=
  270. (token$)
  271.       B%?buffer%=0
  272.       B%+=1
  273.  token%=0
  274. =buffer%
  275. assemble_longest_match
  276.  code%,pass%,P%
  277.  code% 4096
  278.  pass%=0 
  279. P%=code%
  280. [OPT pass%
  281. .__longest_match
  282. \ On entry:
  283. :\        r0->string to try to match dictionary against
  284. \        r1->Dictionary
  285. \ On exit:
  286. \        r0->result block
  287.  \ Format of a dictionary is:
  288. 5\        {<token_number><null-terminated token>}+
  289. 2\        dictionary is terminated by token &00
  290. ! \ Format of result block is:
  291. "&\        Offset  Size  Description
  292. #D\             0     4  Token number of best match (or 0 if none)
  293. $8\             4     4  byte after the matched string
  294. &"str      r13,__lm_system_stack
  295. '1adr      r13,__lm_stack         \ local stack
  296. ()stmfd    r13!,{r14}        \ stack LR
  297. )"bl       __lm_swi_dict_match  
  298. *!adr      r9,__lm_result_block
  299. +:str      r0,[r9,#4]        \ byte after matched string
  300. ,-str      r1,[r9]           \ token number
  301. -Qmov      r0,r9             \ so 
  302.  will yield a pointer to __lm__result_block 
  303. ldmfd    r13!,{r14}
  304. /"ldr      r13,__lm_system_stack
  305. movs     pc,r14
  306. 2!.__lm_system_stack     equd 0
  307. 3(.__lm_result_block     equd 0:equd 0
  308. 4(.__lm_stack_top        equs 
  309. .__lm_stack
  310. 7    ALIGN
  311. .__lm_swi_dict_match
  312. \ On entry:
  313. ;:\        r0->string to try to match dictionary against
  314. \        r1->Dictionary
  315. \ On exit:
  316. ?*\        r0->byte after matched string
  317. @M\        r1=matching token (or 0 if no match, in which case r0 preserved)
  318. B \ Format of a dictionary is:
  319. C5\        {<token_number><null-terminated token>}+
  320. D2\        dictionary is terminated by token &00
  321. E6mov      r5,#0             \ longest match to date
  322. F5mov      r4,#0             \ and its token number
  323. .__lm_get_next_token
  324. I*ldrb     r2,[r1],#1        \ get token
  325. J8cmp      r2,#0             \ is it the 0 terminator?
  326. K@beq      __lm_finished          \ if so, then we're finished
  327. \ Get match length in r3
  328. N3mov      r3,#0             \ start at 0 matches
  329. O,mov      r6,r0             \ string1 ptr
  330. P,mov      r7,r1             \ string2 ptr
  331. .__lm_matchloop
  332. R6ldrb     r8,[r6],#1        \ get next from string1
  333. S6ldrb     r9,[r7],#1        \ get next from string2
  334. T3cmp      r8,r9             \ are they the same?
  335. U:addeq    r3,r3,#1          \ if matched, matchlength++
  336. V<beq      __lm_matchloop         \ loop until match fails
  337. X?cmp      r9,#0             \ did we match all of the token?
  338. YKmovne    r3,#0             \ if not, then we've matched nothing at all!
  339. ZGcmp      r3,r5             \ is it longer than the last best match?
  340. [Bmovgt    r5,r3             \ if so, record the new best length
  341. \Bmovgt    r4,r2             \ ... and the new best token number
  342. .__lm_find_next_token
  343. _<ldrb     r8,[r1],#1        \ get next char in dictionary
  344. `:cmp      r8,#0             \ is it the NULL terminator
  345. a!bne      __lm_find_next_token
  346. c b        __lm_get_next_token
  347. .__lm_finished
  348. fFadd      r0,r0,r5          \ ->character *after* the longest match
  349. g;mov      r1,r4             \ token number of best match
  350. h%movs     pc,r14            \ exit
  351. =code%
  352.